home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Tools
/
awf
/
pass2.base
< prev
next >
Wrap
Text File
|
1995-05-16
|
21KB
|
589 lines
# second pass: interpretation of directives
# A macro-set-specific portion gets interpolated into this at the "#include"
# line. As a minimum, it must deal with .^b and .^e and with any input traps.
BEGIN {
# stuff for output to third pass
nobreak = -1
dobreak = -2
message = -3
OFS = "\t"
# special-character table; this one character needs to be hardcoded
chars[" "] = " " ; charwidths[" "] = 1
debug["e"] = 0 # just to make it an array
strings["a"] = "" # just to make it an array
numbers["a"] = 0 # just to make it an array
hyphens["a"] = "" # just to make it an array
hyphenwidths["a"] = "" # just to make it an array
# stuff for expression decoding
signfactor["+"] = 1
signfactor["-"] = -1
scale["i"] = 240
scale["c"] = 240*50/127
scale["P"] = 240/6
# we get m, n, and v when we see .^r
scale["p"] = 240/72
scale["u"] = 1
# stuff for basic parameters that just get passed to third pass
parms["in"] = 0 # just to make it an array
prevparms["in"] = 0 # just to make it an array
setcmd["ll"] = "linelen"
setcmd["in"] = "indent"
setcmd["ti"] = "tempindent"
setcmd["po"] = "pageoffset"
setcmd["pl"] = "pagelen"
# did last word end with \c ? (in which case, it's still in "word")
backc = 0
# stuff for error reporting
il = 0 # input line number
lockil = 0 # il is locked, we're inside a macro
inname = "?" # input filename
msg = message "\t" # later picks up filename etc.
# current input trap
afternext = ""
}
{
if (!lockil)
il++
msg = message "\t" inname "," il ": "
# fallthrough
}
/^[ \t]*$/ { # empty line
print dobreak, "space"
next
}
/^[ \t]/ { # line starting with white space
print dobreak, "flush"
print 0, "" # empty word
# fallthrough
}
/^[^.]/ { # text
# dispose of the easy case
if (font == "R" && $0 !~ /\\|\t|-| / && !backc && afternext == "") {
for (i = 1; i <= NF; i++)
print length($i), $i
if ($0 ~ /[.!?:][\])'"*]*$/)
print nobreak, "gap", 2
if (centering > 0) {
print dobreak, "center"
centering--
} else if (!fill)
print dobreak, "flush"
next
}
# the hard case, needs a character-by-character scan
s = $0 " " # the space flushes the last word
n = 1 # current position in s
inword = 0 # have we been processing a word?
period = "" # "." if this word ended a sentence
nsp = 0 # count of spaces seen so far
tabpos = 0 # which tab position was used last
while (n <= length(s)) {
c = substr(s, n, 1)
# handle state transitions
if (c == " " || c == "\t") {
if (inword) { # ends word
if (!backc) {
print wordlen, word
if (usedhyphen)
print nobreak, "nohyphen"
}
inword = 0
nsp = 0
}
} else {
if (!inword) { # begins word
if (!backc) {
word = ""
wordlen = 0
usedhyphen = 0
}
backc = 0
inword = 1
if (nsp > 1)
print nobreak, "gap", nsp
}
}
# deal with the character
if (c == " ") {
nsp++
if (n != length(s)) # not the trailing flusher
period = ""
} else if (c == "\t") {
# not really right, should be based on input position
# also, one space following tab gets ignored
tabpos++
if (tabpos <= ntabs)
print nobreak, "tabto", tabs[tabpos]
nsp = 0
period = ""
} else if (c == "-" && wordlen > 0) {
# hyphen within word
print wordlen, word, hyphenwidths[font]
print nobreak, "userhyphen", hyphens[font], hyphenwidths[font]
word = ""
wordlen = 0
period = ""
usedhyphen = 1
} else if (c != "\\") {
# ordinary character
if (font == "B")
word = word c "\b" c "\b" c
else if (font == "I" && c ~ /[a-zA-Z0-9]/)
word = word "_\b" c
else
word = word c
wordlen++
if (c ~ /[.!?:]/)
period = "."
else if (c !~ /[\])'"*]/)
period = ""
} else { # backslash
n++
c = substr(s, n, 1)
if (c == "f") {
# font change
n++
code = substr(s, n, 1)
if (code == "(") {
n++
code = substr(s, n, 2)
n++
}
if (code == "P")
font = prevfont
else if (fontok[code] == "")
print msg "unknown font `" code "'"
else {
prevfont = font
font = code
}
} else if (c == "n") {
# number-register value
n++
code = substr(s, n, 1)
if (code == "(") {
n++
code = substr(s, n, 2)
n++
}
s = substr(s, 1, n) numbers[code] substr(s, n+1)
} else if (c == "s") {
# size change
n++
if (substr(s, n, 1) ~ /[0-9]/)
n++
# just ignore it
} else if (c == "c")
# word continuation
backc = 1
else if (c == "*") {
# string-variable value
n++
code = substr(s, n, 1)
if (code == "(") {
n++
code = substr(s, n, 2)
n++
}
s = substr(s, 1, n) strings[code] substr(s, n+1)
} else if (c == "%") {
# discretionary hyphen
if (wordlen > 0) {
print wordlen, word, hyphenwidths[font]
print nobreak, "hyphen", hyphens[font], hyphenwidths[font]
word = ""
wordlen = 0
usedhyphen = 1
}
} else if (c == "(" && substr(s, n+1, 2) == "em" && \
chars["em"] != "") {
# em-dash, special case due to hyphenation
n += 2
emw = charwidths["em"]
print wordlen, word, emw
print nobreak, "userhyphen", chars["em"], emw
word = ""
wordlen = 0
period = ""
usedhyphen = 1
} else {
# special-character name
code = c
if (code == "(") {
n++
code = substr(s, n, 2)
n++
}
word = word chars[code]
wordlen += charwidths[code]
period = ""
}
}
# on to the next character, at last
n++
}
# end-of-line processing
if (!backc) {
if (period == ".")
print nobreak, "gap", 2
if (centering > 0) {
print dobreak, "center"
centering--
} else if (!fill)
print dobreak, "flush"
}
# if no input trap, we're done
if (afternext == "")
next
# if there is an input trap, fall into the macro-dependent section
}
#
#
#
# at this point we plug in the macro-specific stuff, keyed on the next line
#include note that this is an awk comment
#
#
#
/^\.it/ { # plant an input trap, sort of
if (NF > 1 && $2 != 1)
print msg ".it first argument must be 1"
if (NF > 2)
afternext = afternext "," $3
else
afternext = ""
next
}
/^\.\^r cpi / { # set resolutions, in cpi: .^r cpi hor vert
scale["m"] = 240/$3
scale["n"] = 240/$3
scale["v"] = 240/$4
next
}
/^\.(ta|ll|in|ti|po|ne|sp|pl|nr)/ { # expression processing
# sort out default scale factor
if ($1 ~ /^\.(ne|sp|pl)/)
exprscale = "v"
else if ($1 ~ /^\.(nr)/)
exprscale = "u"
else
exprscale = "n"
# which argument should we start with?
offset = length($1) + 1
if ($1 == ".nr")
offset += length($2) + 1
# beginning of debugging message
if (debug["e"])
printf "%s ", msg substr($0, 1, offset)
# do the expressions
s = substr($0, offset+1)
n = 1
while (s != "") {
while (s ~ /^[ \t]/)
s = substr(s, 2)
# an initial sign is magic
ssign = ""
if (s ~ /^[+-]/) {
ssign = substr(s, 1, 1)
s = substr(s, 2)
}
s = "+" s # this is an un-magic addition operator
# process terms
sval = 0
# there is no portable way to put a slash in a regexp
while (s ~ /^[+*%)-]/ || substr(s, 1, 1) == "/") {
# figure out what it is and what it contributes
if (debug["e"] > 1)
print "s=`" s "'"
termop = substr(s, 1, 1)
s = substr(s, 2)
termscale = exprscale
if (termop == ")") {
if (debug["e"] > 1)
print "pop " valstack[vsp] " " opstack[vsp] " with " sval
termval = sval
sval = valstack[vsp]
termop = opstack[vsp]
vsp--
termscale = "u"
} else if (s ~ /^\(/) {
if (debug["e"] > 1)
print "push " sval " " termop
vsp++
valstack[vsp] = sval
opstack[vsp] = termop
sval = 0
termop = "+" # dummy op and value
termval = 0
s = "+" substr(s, 2)
} else if (s ~ /^\\w/) {
delim = substr(s, 3, 1)
s = substr(s, 4)
endp = index(s, delim)
if (endp == 0)
endp = length(s) + 1
termval = (endp - 1) * scale["n"] # crude
s = substr(s, endp+1)
} else if (s ~ /^\\n/) {
if (s ~ /^\\n\(/) {
code = substr(s, 4, 2)
s = substr(s, 6)
} else {
code = substr(s, 3, 1)
s = substr(s, 4)
}
termval = numbers[code]
} else if (s ~ /^[0-9.]/) {
for (endp = 1; endp <= length(s); endp++)
if (substr(s, endp, 1) !~ /[0-9.]/)
break
termval = substr(s, 1, endp-1) + 0
s = substr(s, endp)
}
# add it in, with scaling factor
c = substr(s, 1, 1)
if (scale[c] != "") {
termval *= scale[c]
s = substr(s, 2)
} else
termval *= scale[termscale]
if (termop == "+")
sval += termval
else if (termop == "-")
sval -= termval
else if (termop == "*")
sval *= termval
else if (termop == "/")
sval = int(sval) / int(termval)
else if (termop == "%")
sval = int(sval) % int(termval)
}
# remember the value, print if debugging
expr[n] = sval
exprsign[n] = ssign
iexpr[n] = signfactor[ssign] * sval # convenience
if (debug["e"])
printf "%s ", ssign "(" sval ")"
# proceed to next, skipping trash if necessary
while (s ~ /^[^ \t]/)
s = substr(s, 2)
n++
}
# final cleanup
nexprs = n - 1
if (debug["e"])
printf "\n"
# fallthrough
}
/^\.(ll|in|ti|po|pl)/ { # common code for set-parameter requests
# relies on expression processing, including setting of exprscale
name = substr($1, 2, 2)
n = parms[name]
if (nexprs == 0)
n = prevparms[name]
else if (exprsign[1] == "" || name == "ti")
n = expr[1] / scale[exprscale]
else
n += iexpr[1] / scale[exprscale]
prevparms[name] = parms[name]
parms[name] = int(n)
print dobreak, setcmd[name], parms[name]
next
}
/^\.nr/ {
# relies on expression processing
n = numbers[$2]
if (exprsign[1] == "")
n = expr[1]
else
n += iexpr[1]
numbers[$2] = int(n)
next
}
/^\.ne/ {
# relies on expression processing
print dobreak, "need", int(expr[1]/scale["v"] + 0.99)
next
}
/^\.sp/ {
# relies on expression processing
if (nexprs == 0)
i = 1
else
i = int(expr[1]/scale["v"] + 0.99)
for (; i > 0; i--)
print dobreak, "space"
next
}
/^\.ta/ {
# relies on expression processing
tabstop = 0
for (n = 1; n <= nexprs; n++) {
if (exprsign[n] == "")
tabstop = expr[n]
else
tabstop += iexpr[n]
tabs[n] = int(tabstop/scale["n"])
}
ntabs = nexprs
next
}
/^\.ft/ {
if (NF > 1)
code = $2
else
code = "P"
if (code == "P")
font = prevfont
else if (fontok[code] == "")
print msg "unknown font `" code "'"
else {
prevfont = font
font = code
}
next
}
/^\.br/ {
print dobreak, "flush"
next
}
/^\.ds/ {
# note, macro-set-specific code often looks at .ds as well
if ($3 !~ /^"/)
strings[$2] = $3
else
strings[$2] = substr($0, index($0, "\"")+1)
next
}
/^\.ns/ {
print nobreak, "nospace"
next
}
/^\.rs/ {
print nobreak, "yesspace"
next
}
/^\.ad/ {
print nobreak, "both"
next
}
/^\.na/ {
print nobreak, "left"
next
}
/^\.nf/ {
fill = 0
print dobreak, "flush"
next
}
/^\.fi/ {
fill = 1
print dobreak, "flush"
next
}
/^\.\^x/ { # direct errors to this file: .^x filename
print nobreak, "errsto", $2
next
}
/^\.\^c/ { # define character: .^c name width text
if ($4 ~ /^"/)
s = substr($0, index($0, "\"")+1)
else
s = $4
ns = ""
while ((n = index(s, "\\")) > 0) {
if (n > 1)
ns = ns substr(s, 1, n-1)
n++
c = substr(s, n, 1)
if (c == "\\")
ns = ns "\\"
else if (c == "b")
ns = ns "\b"
s = substr(s, n+1)
}
ns = ns s
if ($2 == "hy") {
hyphens[font] = ns
hyphenwidths[font] = $3
} else {
chars[$2] = ns
charwidths[$2] = $3
}
next
}
/^\.\^f/ { # this font is okay: .^f fontname
# someday, this might take font-change codes as further arguments
fontok[$2] = "yes"
next
}
/^\.tm/ {
print msg $0
next
}
/^\.ps/ {
# ignore
next
}
/^\.ce/ {
if (NF > 1)
centering = $2
else
centering = 1
next
}
/^\.bp/ {
print dobreak, "need", 999
next
}
/^\.\^d/ { # debug control: .^d debugvar value
debug[$2] = $3
next
}
/^\.\^#/ { # set line number of next line: .^# no file
il = $2 - 1
lockil = 0
inname = $3
next
}
/^\.\^=/ { # lock line number to value: .^= no file
il = $2
lockil = 1
inname = $3
next
}
/^\.\\"/ { # comment
next
}
/^\./ {
print msg "command `" $1 "' unsupported or unknown"
}
END {
print dobreak, "need", 999 # flush page
}